/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package treegen;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import javafx.geometry.Insets;
import javafx.scene.control.ComboBox;
import jfx.messagebox.MessageBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.Text;
import javafx.util.Callback;

/**
 * Класс уровня ветвей. Класс предназначен для хранения и получения данных от пользователя о всех параметрах, характеризующих ветви.
 * @author Елена
 */
public class BranchLevel {

    /** Главная панель*/
    VBox mainPane;
    /** Виджет для ввода длины*/
    public NumberSpinner length;
    /** Виджет для ввода ширины*/
    public NumberSpinner width;
    /** Виджет для ввода расстояния по стволу*/
    public NumberSpinner rad;
    /** Виджет для ввода высоты*/
    public NumberSpinner height;
    /** Виджет для ввода угла*/
    public NumberSpinner angle;
    /** Виджет для ввода количества дочерних ветвей*/
    public NumberSpinner childCount;
    /** Виджет для ввода количества повторений дочерних ветвей*/
    public NumberSpinner childRep;
    /** Виджет для ввода расстояния по высоте*/
    public NumberSpinner heightL;
    /** Виджет для ввода типа ветви*/
    public ComboBox combo;
    /** Номер уровня*/
    int number;
    /** Дерево*/
    Tree tree;

    /**
     * Конструктор для создания уровня
     * @param number номер уровня
     * @param tree дерево
     */
    BranchLevel(int number, Tree tree) {

        this.number = number;
        this.tree = tree;
        mainPane = new VBox();
        // Виджет для длины
        HBox lBox = new HBox();
        Text textL = new Text("Длина ветви:");
        textL.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        length = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"), (float) 0.00, (float) 1000000.0);
        lBox.getChildren().addAll(textL, length);
        lBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для ширины
        HBox wBox = new HBox();
        Text textW = new Text("Ширина ветви:");
        textW.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        width = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"), (float) 0.00, (float) 1000000.0);
        wBox.getChildren().addAll(textW, width);
        wBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для расстояния
        HBox rBox = new HBox();
        Text textR = new Text("Расстояние между ветками по стволу:");
        textR.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        rad = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"), (float) 0.00, (float) 1000000.0);
        rBox.getChildren().addAll(textR, rad);
        rBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для расстояния
        HBox hBox = new HBox();
        Text textH = new Text("Высота между ветками по стволу:");
        textH.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        height = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"), (float) 0.00, (float) 1000000.0);
        hBox.getChildren().addAll(textH, height);
        hBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для угла
        HBox aBox = new HBox();
        Text textA = new Text("Угол к стволу:");
        textA.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        angle = new NumberSpinner((float) 0, (float) 180);
        aBox.getChildren().addAll(textA, angle);
        aBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для кол-ва дочерних ветвей
        HBox cBox = new HBox();
        Text textC = new Text("Количество дочерних ветвей:");
        textC.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        childCount = new NumberSpinner((float) 0, (float) 10);
        cBox.getChildren().addAll(textC, childCount);
        cBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для кол-ва  повторений дочерних ветвей
        HBox cRBox = new HBox();
        Text textCR = new Text("Количество повторений дочерних ветвей:");
        textCR.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        childRep = new NumberSpinner((float) 0, (float) 5);
        cRBox.getChildren().addAll(textCR, childRep);
        cRBox.setPadding(new Insets(0, 0, 10, 0));

        // Виджет для высоты уровня
        HBox hLBox = new HBox();
        Text textHL = new Text("Высота уровня:");
        textHL.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        heightL = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"), (float) 0.00, (float) 1000000.0);
        hLBox.getChildren().addAll(textHL, heightL);
        hLBox.setPadding(new Insets(0, 0, 10, 0));

        HBox right = new HBox();
        Text r = new Text("Прямой");
        r.setFont(Font.font("Verdana", 12));
        ImageView rig = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/right.jpg")));
        right.getChildren().addAll(rig, r);

        combo = new ComboBox();
        combo.getItems().addAll(
                "Прямой",
                "Изогнутый вверх",
                "Изогнутый вниз"
        );

        HBox comboB = new HBox();
        Text com = new Text("Тип:");
        com.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));

        comboB.setPadding(new Insets(0, 0, 10, 0));
        Callback<ListView<String>, ListCell<String>> factory = new Callback<ListView<String>, ListCell<String>>() {
            @Override
            public ListCell<String> call(ListView<String> list) {
                return new ImageCell();
            }
        };
        combo.setCellFactory(factory);
        combo.setButtonCell(factory.call(null));
        comboB.getChildren().addAll(com, combo);
        combo.setValue("Прямой");

        mainPane.getChildren().addAll(lBox, wBox, rBox, hBox, aBox, cBox, cRBox, hLBox, comboB);
        mainPane.setPadding(new Insets(5, 0, 5, 10));

    }

    /**
     * Очистить все виджеты
     */
    public void clear() {
        this.length.setDefaultNumber(new BigDecimal("0.00"));
        this.rad.setDefaultNumber(new BigDecimal("0.00"));
        heightL.setDefaultNumber(new BigDecimal("0.00"));
        this.width.setDefaultNumber(new BigDecimal("0.00"));
    }

    /**
     * Получить значения
     * @return удачно ли прошло считывание?
     */
    public boolean getValues() {
        double width;
        double length;
        double rad;
        double angle;
        double levHeight;
        boolean result = true;
        Branch curBranch = tree.branches.get(number);
        if (tree.trunks.get(0).isSet) {
            // Проверка от ствола
            length = this.length.getNumber().doubleValue();
            if (length >= 0.5 * tree.trunks.get(0).getHeight()) {
                this.length.setDefaultNumber(new BigDecimal("0.00"));
                MessageBox.show(tree.window._stage,
                        "\nДлина ветви должна быть меньше 50% от высоты ствола!",
                        "Ограничения",
                        MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                result = false;

            } else {
                curBranch.length = length;
                width = this.width.getNumber().doubleValue();
                if (width > 0.2 * length || width < 0.05 * length) {
                    this.width.setDefaultNumber(new BigDecimal("0.00"));
                    MessageBox.show(tree.window._stage,
                            "\nШирина ветви должна быть не более 20%  и не менее 5% от длины!",
                            "Ограничения",
                            MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                    result = false;
                } else {
                    curBranch.width = width;
                    // Проверка от ствола

                    rad = this.rad.getNumber().doubleValue();
                    if (rad > tree.trunks.get(0).getWidth() * Math.PI) {
                        this.rad.setDefaultNumber(new BigDecimal("0.00"));
                        MessageBox.show(tree.window._stage,
                                "\nСлишком большое расстояние между ветками по стволу!",
                                "Ограничения",
                                MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                        result = false;
                    } else {
                        curBranch.radByTrunk = rad;
                        curBranch.heightByTrunk = height.getNumber().doubleValue();
                        angle = this.angle.getNumber().doubleValue();
                        if (angle <= 0 || angle >= 180) {
                            this.angle.setDefaultNumber(new BigDecimal("0.00"));
                            MessageBox.show(tree.window._stage,
                                    "\nУгол должен быть больше 0 и меньше 180 градусов!",
                                    "Ограничения",
                                    MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                            result = false;
                        } else {
                            curBranch.angle = angle;
                            curBranch.childrenCount = childCount.getNumber().intValue();
                            curBranch.repetCount = childRep.getNumber().intValue();

                            levHeight = heightL.getNumber().doubleValue();
                            // Проверка от ствола
                            if (levHeight < 0.15 * tree.trunks.get(0).getHeight() || levHeight > tree.trunks.get(0).getHeight()) {
                                heightL.setDefaultNumber(new BigDecimal("0.00"));
                                MessageBox.show(tree.window._stage,
                                        "\nВысота уровня должна быть не менее 15% от высоты ствола и не больше высоты ствола!",
                                        "Ограничения",
                                        MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                                result = false;
                            } else {
                                curBranch.height = levHeight;

                                int type = combo.getButtonCell().getIndex();
                                if (type == 0) {
                                    curBranch.strType = "Прямой";
                                    curBranch.type = BranchType.Right;
                                } else if (type == 1) {
                                    curBranch.strType = "Изогнутый вниз";
                                    curBranch.type = BranchType.Up;
                                } else {
                                    curBranch.strType = "Изогнутый вверх";
                                    curBranch.type = BranchType.Down;
                                }
                            }
                        }
                    }
                }
            }
        } else {
            clear();
            MessageBox.show(tree.window._stage,
                    "\nСначала необходимо задать парметры ствола",
                    "Ограничения",
                    MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
            result = false;
        }
        return result;
    }

    /**
     * Класс ячейки с изображением для виджета с выбором.
     */
    static class ImageCell extends ListCell<String> {

        @Override
        /**
         * Обновить запись.
         */
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (item != null) {
                if (item.contains("Прямой")) {
                    HBox right = new HBox();
                    Text r = new Text("Прямой");
                    r.setFont(Font.font("Verdana", 12));
                    ImageView rig = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/right.jpg")));
                    right.getChildren().addAll(rig, r);
                    setGraphic(right);
                } else if (item.contains("Изогнутый вниз")) {
                    HBox down = new HBox();
                    Text d = new Text("Изогнутый вниз");
                    d.setFont(Font.font("Verdana", 12));
                    ImageView dow = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/up.jpg")));
                    down.getChildren().addAll(dow, d);
                    setGraphic(down);
                } else {
                    HBox up = new HBox();
                    Text u = new Text("Изогнутый вверх");
                    u.setFont(Font.font("Verdana", 12));
                    ImageView upp = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/down.jpg")));
                    up.getChildren().addAll(upp, u);
                    setGraphic(up);
                }
            }
        }
    }
}
